home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Maclife 157
/
MACLIFE157-2001-09.ISO.7z
/
MACLIFE157-2001-09.ISO
/
Linux
/
MacOS Tools
/
Other
/
BootX 1.1.3 (for Old Mac OS)
/
Sources
/
src
/
LowLevelPPC.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-07-23
|
11KB
|
433 lines
/* This code fragments provides the low-level 68k boot code
with some PPC functions (necessary for using the name
registry API for example).
*/
#include <PCI.h>
#include <Errors.h>
#include <MixedMode.h>
#include <CodeFragments.h>
#include <Gestalt.h>
#include <string.h>
#include "BootX.h"
#include "LowLevelBoot.h"
#ifndef BROKEN_THIRD_PARTY_CARDS
#define BROKEN_THIRD_PARTY_CARDS 1
#endif
#define MAX_STRING_PROP_SIZE 256
#define MAX_ASSIGNED_ADDRESSES 8
#define kPCIConfigCommandAddress 0x04 /* PCI "Command" config register address */
#define cwCommandEnableMemorySpace 0x0002 /* enable memory space bit */
#define cwCommandEnableIOSpace 0x0001 /* enable i/o space bit */
/* Exported */
extern void* main(void);
extern void ShutDownDevices(boot_infos_t* bi);
UInt32 __procinfo = kCStackBased | RESULT_SIZE(SIZE_CODE(sizeof(void*)));
typedef void (*iterate_device_proc)(RegEntryIDPtr entryID);
static OSErr iterate_devices(iterate_device_proc proc);
static SInt32 read_pci_config_reg(RegEntryIDPtr entryID, int reg);
static UInt32 get_base_for_register(PCIAssignedAddress* inAddresses, long inMaxAddresses, long inRegister);
static UInt32 get_assigned_addresses(RegEntryIDPtr entryID, PCIAssignedAddress* outAddresses);
static void get_string_property(RegEntryIDPtr entryID, char* prop_name, char *out_string);
static UInt32 get_io_addresses(RegEntryIDPtr entryID, UInt32 *out_addresses);
static Boolean check_vendor_device_id(RegEntryIDPtr entryID, UInt16 vendorID, UInt16 deviceID);
static void reset_apple_SCSI_UW_board(RegEntryIDPtr entryID);
static void reset_apple_DBDMA_channels(RegEntryIDPtr entryID);
static void reset_apple_USB(RegEntryIDPtr entryID);
static void reset_ATI_mach64_master(RegEntryIDPtr entryID);
static void remap_PDM_video(void);
void*
main(void)
{
return (void *)NewRoutineDescriptor((ProcPtr)ShutDownDevices, uppLowLevelBootPPCProcInfo, kPowerPCISA);
}
void ShutDownDevices(boot_infos_t* bi)
{
/* NuBus: Change address of PDM framebuffer */
if ((long)RegistryEntryIDInit == kUnresolvedCFragSymbolAddress)
{
if (bi->architecture & BOOT_ARCH_NUBUS_PDM) {
/* This should definitely be smarter !!! */
if ((UInt32)bi->dispDeviceBase <= 0x100000) {
int i;
remap_PDM_video();
bi->logicalDisplayBase = (UInt8*)0x100000;
bi->dispDeviceBase = (UInt8*)0x100000;
for(i=0; i<bi->physMemoryMapSize; i++) {
if ((bi->physMemoryMap[i].physAddr <= (UInt32)bi->dispDeviceBase) &&
((bi->physMemoryMap[i].physAddr + bi->physMemoryMap[i].size)
> (UInt32)bi->dispDeviceBase)) {
int count = bi->physMemoryMapSize;
int size = bi->physMemoryMap[i].size;
memmove(&bi->physMemoryMap[i+1], &bi->physMemoryMap[i],
sizeof(boot_info_map_entry_t) * (count-i-1));
bi->physMemoryMap[i].size = (UInt32)bi->dispDeviceBase - bi->physMemoryMap[i].physAddr;
bi->physMemoryMap[i+1].physAddr = (UInt32)bi->dispDeviceBase + 0x100000;
bi->physMemoryMap[i+1].size = (size + bi->physMemoryMap[i].physAddr - bi->physMemoryMap[i+1].physAddr);
break;
}
}
}
}
} else {
/* PCI: Disable DMA on known devices */
iterate_devices(reset_apple_SCSI_UW_board);
iterate_devices(reset_apple_DBDMA_channels);
iterate_devices(reset_apple_USB);
iterate_devices(reset_ATI_mach64_master);
}
}
#if BROKEN_THIRD_PARTY_CARDS
inline asm fixed_eieio(void) {
li r0,0;
cmpwi r0,0;
bne+ toto;
eieio;
toto:;
}
#else
#define fixed_eieio() __eieio()
#endif
static void
remap_PDM_video(void)
{
unsigned char savevalue[35];
int i;
*((volatile unsigned char *)0x50F40008) = 0; /* reset bit counter */
fixed_eieio();
for (i=0; i<35; i++) {
savevalue[i] = *((volatile unsigned char *)0x50F40000);
fixed_eieio();
}
savevalue[33] = 0; /* change Video Base to 1Mb */
*((volatile unsigned char *)0x50F40008) = 0; /* reset bit counter again */
fixed_eieio();
for (i=0; i<35; i++) {
*((volatile unsigned char *)0x50F40000) = savevalue[i];
fixed_eieio();
}
}
static UInt32
get_base_for_register( PCIAssignedAddress* inAddresses,
long inMaxAddresses,
long inRegister)
{
UInt32 i;
for (i=0; i<inMaxAddresses; i++)
{
if (inAddresses[i].registerNumber == inRegister)
return inAddresses[i].address.lo;
}
return NULL;
}
static void
get_string_property(RegEntryIDPtr entryID, char* prop_name, char *out_string)
{
OSErr err;
RegPropertyValueSize size;
size = MAX_STRING_PROP_SIZE-1;
err = RegistryPropertyGet(entryID, prop_name, out_string, &size);
if (err == noErr)
out_string[size] = 0;
else
out_string[0] = 0;
}
static UInt32
get_assigned_addresses(RegEntryIDPtr entryID, PCIAssignedAddress* outAddresses)
{
OSErr err;
RegPropertyValueSize size;
size = MAX_ASSIGNED_ADDRESSES * sizeof(PCIAssignedAddress);
err = RegistryPropertyGet(entryID, kPCIAssignedAddressProperty, outAddresses, &size);
if (err == noErr)
return size/sizeof(PCIAssignedAddress);
else
return 0;
}
static UInt32
get_io_addresses(RegEntryIDPtr entryID, UInt32 *out_addresses)
{
UInt32 pSize;
OSStatus err;
pSize = 4 * MAX_ASSIGNED_ADDRESSES;
err = RegistryPropertyGet(entryID, "AAPL,address", out_addresses, &pSize);
if (err == noErr)
return pSize/4;
else
return 0;
}
static Boolean
check_vendor_device_id(RegEntryIDPtr entryID, UInt16 vendorID, UInt16 deviceID)
{
UInt32 pSize;
OSStatus err;
UInt16 prop;
pSize = 2;
err = RegistryPropertyGet(entryID, "vendor-id", &prop, &pSize);
if ((err != noErr)||(pSize != 2))
return false;
if (prop != vendorID)
return false;
pSize = 2;
err = RegistryPropertyGet(entryID, "device-id", &prop, &pSize);
if ((err != noErr)||(pSize != 2))
return false;
return (prop == deviceID);
}
static SInt32
read_pci_config_reg(RegEntryIDPtr entryID, int reg)
{
OSStatus status;
UInt16 value;
status = ExpMgrConfigReadWord(entryID, (LogicalAddress)reg, &value);
if (status != noErr)
return -1;
return value;
}
void
reset_apple_DBDMA_channels(RegEntryIDPtr entryID)
{
char prop[MAX_STRING_PROP_SIZE];
UInt32 addrs[MAX_ASSIGNED_ADDRESSES];
UInt32 addrs_count;
UInt32 *io_base;
get_string_property(entryID, "device_type", prop);
if (strcmp(prop, "dbdma") && strcmp(prop, "device_type"))
return;
addrs_count = get_io_addresses(entryID, addrs);
if (addrs_count < 1)
return;
io_base = (UInt32 *)(addrs[0]);
if (io_base) {
int i;
io_base += (0x2000); /* base of DBDMA channels */
for (i=0;i<16;i++) {
*(io_base) = 0x000000FCUL;
__eieio();
while((*(io_base+1)) & 0x00800000UL)
__eieio();
}
}
}
void
reset_apple_SCSI_UW_board(RegEntryIDPtr entryID)
{
char prop[MAX_STRING_PROP_SIZE];
Boolean found = false;
Boolean use_io = false;
char* io_base;
SInt32 cmd;
PCIAssignedAddress addrs[MAX_ASSIGNED_ADDRESSES];
UInt32 addrs_count;
get_string_property(entryID, "name", prop);
found = (strcmp(prop, "Apple53C875Card") == 0);
if (!found)
found = check_vendor_device_id(entryID, 0x1000, 0xf);
if (!found)
return;
cmd = read_pci_config_reg(entryID, kPCIConfigCommandAddress);
use_io = (cmd > 0) && (cmd & cwCommandEnableIOSpace);
addrs_count = get_assigned_addresses(entryID, addrs);
if (addrs_count < 2)
return;
if (use_io) {
io_base = (char *)get_base_for_register(addrs, MAX_ASSIGNED_ADDRESSES, 16);
if (!io_base)
use_io = false;
}
if (!use_io)
io_base = (char *)get_base_for_register(addrs, MAX_ASSIGNED_ADDRESSES, 20);
if (!io_base)
return;
if (use_io)
ExpMgrIOWriteByte(entryID, (LogicalAddress)0x14, 0x40);
else
*(io_base + 0x14) = 0x40;
__eieio();
}
void
reset_apple_USB(RegEntryIDPtr entryID)
{
char prop[MAX_STRING_PROP_SIZE];
UInt32 addrs[MAX_ASSIGNED_ADDRESSES];
UInt32 addrs_count;
UInt32 *io_base;
get_string_property(entryID, "name", prop);
if (strcmp(prop, "usb"))
return;
get_string_property(entryID, "device_type", prop);
if (strcmp(prop, "usb"))
return;
addrs_count = get_io_addresses(entryID, addrs);
if (addrs_count < 1)
return;
io_base = (UInt32 *)(addrs[0]);
if (io_base) {
*(io_base + 0x02) = 0x01000000UL;
__eieio();
}
}
#define ATI_BUS_MSTR_RESET 0x00000002
#define ATI_BUS_FLUSH_BUF 0x00000004
#define ATI_BUS_CNTL 0x00a0
#define ATI_GUI_ENGINE_ENABLE 0x0100
#define ATI_GEN_TEST_CNTL 0x00d0
#define ATI_BUS_HOST_ERR_ACK 0x00800000
#define ATI_BUS_FIFO_ERR_ACK 0x00200000
static inline void ati_regw(unsigned long base_addr, volatile unsigned long regindex, unsigned long regdata)
{
__stwbrx(regdata, (void *)base_addr, (int)regindex);
__eieio();
}
static inline unsigned long ati_regr(unsigned long base_addr, volatile unsigned long regindex)
{
unsigned long val;
val = __lwbrx((void *)base_addr, regindex);
__eieio();
return val;
}
void
reset_ATI_mach64_master(RegEntryIDPtr entryID)
{
char prop[MAX_STRING_PROP_SIZE];
PCIAssignedAddress addrs[MAX_ASSIGNED_ADDRESSES];
UInt32 io_addrs[MAX_ASSIGNED_ADDRESSES];
UInt32 addrs_count;
UInt32 base;
get_string_property(entryID, "name", prop);
if (strncmp(prop, "ATY", 3))
return;
addrs_count = get_assigned_addresses(entryID, addrs);
switch(addrs_count) {
case 1:
if (get_io_addresses(entryID, io_addrs) > 0)
addrs[0].address.lo = io_addrs[0];
case 2:
case 3:
base = addrs[0].address.lo;
break;
case 4:
base = addrs[1].address.lo;
break;
default:
return;
}
if (!base)
return;
/* reset bus master */
ati_regw(base, ATI_BUS_CNTL, ati_regr(base, ATI_BUS_CNTL) | ATI_BUS_MSTR_RESET);
/* flush buffer, if bus mastering was memory <-> frame buffer */
ati_regw(base, ATI_BUS_CNTL, ati_regr(base, ATI_BUS_CNTL) | ATI_BUS_FLUSH_BUF);
/* reset graphic engine and clear errors, if bus mastering */
/* was memory -> command queue or HOST_DATA */
ati_regw(base, ATI_GEN_TEST_CNTL, ati_regr(base, ATI_GEN_TEST_CNTL) & ~ATI_GUI_ENGINE_ENABLE);
ati_regw(base, ATI_GEN_TEST_CNTL, ati_regr(base, ATI_GEN_TEST_CNTL) | ATI_GUI_ENGINE_ENABLE);
/* No effect for at least 3D RageLTPro, but an insurance. */
ati_regw(base, ATI_BUS_CNTL, ati_regr(base, ATI_BUS_CNTL) | ATI_BUS_HOST_ERR_ACK | ATI_BUS_FIFO_ERR_ACK);
}
static OSErr
iterate_devices(iterate_device_proc proc)
{
RegEntryIter iterator;
RegEntryIterationOp operation;
unsigned long address = 0;
OSStatus err;
Boolean done, found;
char buffer[1024];
char* namePtr;
// Create an Iterator
operation = kRegIterContinue;
err = RegistryEntryIterateCreate(&iterator);
if (err == noErr) {
RegEntryID entryID;
do {
RegPropertyValueSize pSize;
pSize = 255;
done = false;
found = false;
namePtr = buffer;
err = RegistryEntrySearch( &iterator,
operation,
&entryID,
&done,
"name",
namePtr,
pSize
);
if (!done && (err == noErr))
proc(&entryID);
} while (!done && (err == noErr));
}
err = RegistryEntryIterateDispose(&iterator);
return found ? noErr : fnfErr;
}